#!/opt/perl/bin/perl -w

#########################################################################
# Name:		activity [cm2 activity report]				#
#									#
# Author:	Simon Edwards, Proprius Consulting Ltd,			#
#			[simon.edwards@proprius.co.uk]			#
#									#
# Completed:	28th June, 2006.					#
#									#
# Updated:								#
#									#
# Arguments:	[--verbose] [--projects x,ab,c] [--period N[hd]]	#
#									#
#		--verbose     Verbose mode - show progress messages	#
#			      to STDOUT.				#
#		--projects    A comma separated list of projects to	#
#			      scan for changes.				#
#		--period      Go back from now for this period of 	#
#			      time - must be followed by "h" for	#
#			      hours, "d" for days (defaults to 		#
#			      days).					#
#									#
# Purpose:	Genenerates a report which is time-based and shows	#
#		all activity across the specified projects. If the	#
#		same file has been edited in multiple environments	#
#		over the same time period these are highlighted.	#
#									#
#########################################################################

BEGIN {
	push @INC,$ENV{CODEMGR_LIBS} if exists($ENV{CODEMGR_LIBS});
}

use Getopt::Long;
use codemgr2 qw(msg logmsg warnmsg errormsg load_config get_project
		get_related_project_mappings parse_rlog
		get_md5_of_version get_lver_of_md5_version match_version
		load_translog_after_time attempt_alias_map);
use File::Basename;
use Data::Dumper;
use Cwd;
use English;

umask 002;
$_PRG=basename($0);
$_SPC=" " x length($_PRG);
$ARG_projects=undef;
$ARG_verbose=0;
$ARG_period=undef;

sub usage {
	print "
Usage: $_PRG --projects a[,b...] --period N[hd] [--verbose] 

The $_PRG reports on any files looking back from the present over the
specified period that have been changing in more than one project.

$_PRG currently the following arguments:

--projects   The list of projects to scan [can use aliases if desired]
--period     The period of time to check back over - default is days,
             add 'h' suffix to change to hours.
--verbose    Verbose mode - show progress messages to STDOUT.

Written by Simon Edwards 2006, proprius.co.uk
";
	exit 1;
}

if(!GetOptions(
	"projects=s"		=> \$ARG_projects,
	"period=s"		=> \$ARG_period,
	"verbose"		=> \$ARG_verbose,
	)) {
	usage;
}

if(!defined($ARG_projects) || !defined($ARG_period)) {
	usage;
}

$PROJECTS_ROOT=$ENV{PROJECTS_ROOT};
if(! -d $ENV{PROJECTS_ROOT}) {
	errormsg("\"PROJECTS_ROOT\" directory \"$PROJECTS_ROOT\" does not exist.",2);
}

#########################################################################
# Work out the time period and if invalid issue the usage again.	#
#########################################################################

if($ARG_period =~ /^\d+$/) {
	$multi=86400;
} else {
	if($ARG_period !~ /^(\d+)([hd])$/) {
		usage;
	}
	$multi=86400 if $2 eq "d";
	$multi=3600 if $2 eq "h";
	$ARG_period=int($1);
}

$oldtime=time - ($ARG_period * $multi);

%RN=();
for $cproj (split(/,/,$ARG_projects)) {
	if(! -d "$PROJECTS_ROOT/$cproj") {
		$alias=$cproj;
		$realname=attempt_alias_map($cproj);
		if(defined($realname)) {
			$cproj=$realname;
			logmsg("Matched project \"$cproj\" via alias \"$alias\".");
		} else {
			errormsg("Project source directory \"$cproj\" does not exist - continuing without it.");
			next;
		}
	}

	#################################################################
	# Work out the repository type for the project.			#
	#################################################################
	$cfg=load_config("$PROJECTS_ROOT/$cproj/.meta");
	if(!defined($cfg)) {
		errormsg("Unable to load project configuration for '$cproj' - aborting.",3);
	}
	$repos_type{$cproj}=1;
	if(exists($cfg->{REPOS_TYPE})) {
		$repos_type{$cproj}=$cfg->{REPOS_TYPE}->[0];
	}

	#################################################################
	# Now load the transload for the specified project.		#
	#################################################################
	($data,$err)=load_translog_after_time($cproj,$oldtime);
	if(defined($err)) {
		errmsg("Error encountered loading transaction details for \"$cproj\":");
		errmsg($err,1);
	}
	$RN{$cproj}=[@$data];
}

for (sort(keys(%RN))) {
	$e=scalar(@{$RN{$_}});
	logmsg(sprintf("Project %-20s has %4d updates.",$_,$e));
}

#########################################################################
# We build a hash using the time as the key for all entries. Each	#
# is a list incase more than 1 thing is registered against the same	#
# time.									#
#########################################################################

%ALLFILES=();
%ALLFILES2=();
@cols=(19,8,4,9,3,8);

for $cproj (sort(keys(%RN))) {
	$cols[1]=length($cproj) if length($cproj)>$cols[1];
	for $centry (@{$RN{$cproj}}) {
		next if $centry->[2] eq "TAG";
		$ctime=$centry->[0];
		$cact=$centry->[2];
		$cact="Check out" if $cact eq "CO";
		$cact="Unlocked" if $cact eq "UL";
		$cact="Check in" if $cact eq "UP";
		$cact="Deleted" if $cact eq "DF";
		$cact="Created" if $cact eq "NF";
		next if length($cact)<4;
		$cols[3]=length($cact) if length($cact)>$cols[3];
		$cfile=$centry->[3];
		$cols[2]=length($cfile)+2 if length($cfile)+2>$cols[2];
		$cuser=$centry->[1];
		$cols[4]=length($cuser) if length($cuser)>$cols[4];
		if(!exists($ALLFILES{$ctime})) {
			$ALLFILES{$ctime}=[];
		}
		if(!exists($ALLFILES2{$cfile})) {
			$ALLFILES2{$cfile}=[];
		}
		#########################################################
		# Parse the log to extract check in comment.		#
		#########################################################

		$txt="";
		if($cact eq "Check in") {
			my $sdir="$PROJECTS_ROOT/$cproj";
			if($repos_type{$cproj}==1) {
				$rinfo=parse_rlog("$sdir/$cfile,v",1);
			} else {
				$rinfo=parse_rlog("$sdir/$cfile,pv",2);
			}
			$txt=$rinfo->{revisions}->{$centry->[4]}->{text};
		}
		push @{$ALLFILES{$ctime}},[$ctime,$cproj,$cfile,$cact,$cuser,$txt];
		if(!scalar(grep {$_ eq $cproj} @{$ALLFILES2{$cfile}})) {
			push @{$ALLFILES2{$cfile}},$cproj;
		}
	}
}

printf("%-*s  %-*s  %-*s  %-*s  %-*s  %-*s\n",
		$cols[0],"Date/Time",
		$cols[1],"Project",
		$cols[2],"  File",
		$cols[3],"Activity",
		$cols[4],"Who",
		$cols[5],"Comment");

for (sort(keys(%ALLFILES))) {
	my @t=localtime($_);
	$ti=sprintf("%04d/%02d/%02d %02d:%02d:%02d",$t[5]+1900,$t[4]+1,$t[3],$t[2],$t[1],$t[0]);
	for $cent (@{$ALLFILES{$_}}) {
		$f=$cent->[2];
		if(scalar(@{$ALLFILES2{$f}})>1) {
			$f="* $f";
		} else {
			$f="  $f";
		}
		printf("%-*s  %-*s  %-*s  %-*s  %-*s  %s\n",
			$cols[0],$ti,
			$cols[1],$cent->[1],
			$cols[2],$f,
			$cols[3],$cent->[3],
			$cols[4],$cent->[4],$cent->[5],
		);
	}
}

exit;
